﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Benchmark_System {
    class LoggerDB {


        public void Subscribe(BenchmarkSystem bms) {
            bms.JobSubmitted += OnJobSubmitted;
            bms.JobCancelled += OnJobCancelled;
            bms.JobRunning += OnJobRunning;
            bms.JobTerminated += OnJobTerminated;
            bms.JobFailed += OnJobFailed;
        }

        /// <summary>
        /// Called when a job is submitted
        /// </summary>
        internal void OnJobSubmitted(object sender, EventArgs ea) {
            JobEvent jobEvent = (JobEvent)ea;
            AddJobToDB(jobEvent.Message());
        }
        /// <summary>
        /// Called when a job is canceled
        /// </summary>
        internal void OnJobCancelled(object sender, EventArgs ea) {
            JobEvent jobEvent = (JobEvent)ea;
            CancelJobFromDB(jobEvent.Message());
        }
        /// <summary>
        /// Called when a job is run
        /// </summary>
        internal void OnJobRunning(object sender, EventArgs ea) {
            try {
                JobEvent jobEvent = (JobEvent)ea;
                int id = jobEvent.Message().id;
                using (var dbContex = new Model1Container()) {
                    var jobs = from job in dbContex.DBJobSet
                               where job.Id == id
                               select job;
                    DBJob j = jobs.FirstOrDefault();
                    j.DBLogger.Run = DateTime.Now;
                    dbContex.SaveChanges();
                }
            }
            catch (Exception e) {
                Console.Error.WriteLine(e);
            }
        }



        /// <summary>
        /// Called when a job is terminated
        /// </summary>
        internal void OnJobTerminated(object sender, EventArgs ea) {
            JobEvent jobEvent = (JobEvent)ea;
            using (var dbContex = new Model1Container()) {
                var jobs = from job in dbContex.DBJobSet
                           where job.Id == jobEvent.Message().id
                           select job;
                jobs.FirstOrDefault().DBLogger.Terminated = DateTime.Now;
                dbContex.SaveChanges();
            }

        }

        /// <summary>
        /// /// Called when a job fails
        /// </summary>
        internal void OnJobFailed(object sender, EventArgs ea) {
            JobEvent jobEvent = (JobEvent)ea;
            using (var dbContex = new Model1Container()) {
                var jobs = from job in dbContex.DBJobSet
                           where job.Id == jobEvent.Message().id
                           select job;
                jobs.FirstOrDefault().DBLogger.Error = DateTime.Now;
                dbContex.SaveChanges();
            }
        }

        /// <summary>
        /// private method to add a job to the DB
        /// </summary>
        /// <param name="job">the job to be added</param>
        private static void AddJobToDB(Job job) {

            using (var dbContex = new Model1Container()) {

                DBLogger dblog = new DBLogger();
                dblog.Submitted = DateTime.Now;
                dblog.Run = null;
                dblog.Terminated = null;
                dblog.Error = null;


                DBJob dbJob = new DBJob();
                dbJob.CPU = "" + job.Cpu;
                dbJob.ExpectedRuntime = "" + job.ExpectedRuntime;

                dbJob.DBLogger = dblog;
                dbContex.DBJobSet.AddObject(dbJob);
                dbContex.DBLoggerSet.AddObject(dblog);

                List<DBOwner> owners = Quries.getAllUsers();
                if (owners.Any(e => e.Name.Equals(job.owner.name))) {

                    var o = from Owner in dbContex.DBOwnerSet
                            where Owner.Name.Equals(job.owner.name)
                            select Owner;

                    dbJob.DBOwner = o.First();


                }
                else {
                    DBOwner dbOwner = new DBOwner();
                    dbOwner.Name = job.owner.name;
                    dbContex.DBOwnerSet.AddObject(dbOwner);
                    dbJob.DBOwner = dbOwner;
                }

                dbContex.SaveChanges();
                job.id = dbJob.Id;
            }

        }

        /// <summary>
        /// private method to cancel this job from the DB
        /// </summary>
        /// <param name="job">the job to be canceled</param>
        private static void CancelJobFromDB(Job job) {
            using (var dbContext = new Model1Container()) {
                var remJob = from dbJob in dbContext.DBJobSet
                             where dbJob.Id == job.id
                             select dbJob;
                DBJob jb = remJob.First();
                dbContext.DeleteObject(jb.DBLogger);
                dbContext.DeleteObject(jb);

                dbContext.SaveChanges();
            }
        }
    }
}
